package controllers

import java.io.File
import java.nio.file.Files

import command.{CommandExec, ExecCommand}
import dao._
import javax.inject.Inject
import play.api.data._
import play.api.data.Forms._
import play.api.libs.json.Json
import play.api.mvc._
import utils.Utils
import play.api.libs.concurrent.Execution.Implicits._
import models.Tables._
import org.apache.commons.io.FileUtils
import org.joda.time.DateTime
import tool.Pojo.CommandData
import tool.Tool

import scala.concurrent.Future

/**
 * Created by yz on 2018/5/23
 */
class ProjectController @Inject()(projectDao: ProjectDao, tool: Tool, groupDao: GroupDao, proteinDealDao: ProteinDealDao) extends Controller {

  def projectManageBefore = Action { implicit request =>
    Ok(views.html.projectManage())
  }

  def mock = Action { implicit request =>
    Redirect(routes.ProjectController.projectManageBefore()).withSession("id" -> "1", "user" -> "yz")
  }

  def toIndex = Action { implicit request =>
    Redirect(routes.ProjectController.projectManageBefore())
  }

  def getAllProject = Action.async { implicit request =>
    val userId = tool.getUserId
    projectDao.selectAll(userId).map { x =>
      val array = Utils.getArrayByTs(x)
      Ok(Json.toJson(array))
    }
  }

  case class ProjectData(projectName: String, describe: String)

  val projectForm = Form(
    mapping(
      "projectName" -> text,
      "describe" -> text
    )(ProjectData.apply)(ProjectData.unapply)
  )

  def addProject = Action.async(parse.multipartFormData) { implicit request =>
    val data = projectForm.bindFromRequest().get
    val userId = tool.getUserId
    val row = ProjectRow(0, userId, data.projectName, data.describe, new DateTime())
    val tmpDataFile = request.body.file("dataFile").get
    val tmpFile = Files.createTempFile("data", ".txt").toFile
    tmpDataFile.ref.moveTo(tmpFile, true)
    val (b, message) = Utils.checkFile(tmpFile)
    if (b) {
      projectDao.insertReturnId(row).map { x =>
        val id = x
        val userIdDir = new File(Tool.dataDir, userId.toString)
        Utils.createDirectoryWhenNoExist(userIdDir)
        val projectIdDir = new File(userIdDir, id.toString)
        Utils.createDirectoryWhenNoExist(projectIdDir)
        val dataFile = new File(projectIdDir, "data.txt")
        val dealFile = new File(projectIdDir, "deal.txt")
        FileUtils.copyFile(tmpFile, dataFile)
        FileUtils.copyFile(dataFile, dealFile)
        tmpFile.delete()
        val tmpListFile = request.body.file("listFile").get
        val listFile = new File(projectIdDir, "list.txt")
        tmpListFile.ref.moveTo(listFile, true)
        val tmpKeggFile = request.body.file("keggFile").get
        val keggFile = new File(projectIdDir, "kegg.txt")
        tmpKeggFile.ref.moveTo(keggFile, true)
        val tmpGoFile = request.body.file("goFile").get
        val goFile = new File(projectIdDir, "go.txt")
        tmpGoFile.ref.moveTo(goFile, true)

        CommandExec().exec { b =>
          val command =
            s"""
               |dos2unix *
               |""".stripMargin
          CommandData(projectIdDir, command)
        }

        Redirect(routes.ProjectController.getAllProject())
      }
    } else {
      tmpFile.delete()
      Future.successful(Ok(Json.obj("valid" -> "false", "message" -> message)))
    }
  }

  case class ProjectNameData(projectName: String)

  val projectNameForm = Form(
    mapping(
      "projectName" -> text
    )(ProjectNameData.apply)(ProjectNameData.unapply)
  )

  def projectNameCheck = Action.async { implicit request =>
    val data = projectNameForm.bindFromRequest.get
    val userId = tool.getUserId
    projectDao.selectByProjectName(userId, data.projectName).map {
      case Some(y) => Ok(Json.obj("valid" -> false))
      case None => Ok(Json.obj("valid" -> true))
    }
  }

  def deleteProjectByProjectId = Action.async { implicit request =>
    val data = tool.projectIdForm.bindFromRequest().get
    val projectId = data.projectId
    groupDao.deleteByProjectId(projectId).zip(projectDao.deleteById(projectId)).zip(proteinDealDao.deleteByProjectId(projectId)).
      map { x =>
        val projectIdDir = tool.getProjectIdDir(projectId)
        Utils.deleteDirectory(projectIdDir)
        val optionProjectId = tool.getOptionProjectId
        if (optionProjectId.isDefined && optionProjectId.get.toInt == projectId) {
          Redirect(routes.ProjectController.getAllProject()).removingFromSession("projectId", "projectName")
        } else {
          Redirect(routes.ProjectController.getAllProject())
        }
      }
  }

  def delete(userId: Int) = Action.async { implicit request =>
    if (request.session.get("admin").isDefined && request.session.get("id").get == "1") {
      projectDao.selectAll(userId).flatMap { projects =>
        val projectIds = projects.map(_.id)
        proteinDealDao.deleteByProjectIds(projectIds).zip(groupDao.deleteByProjectIds(projectIds))
      }.flatMap { x =>
        projectDao.deleteByUserId(userId)
      }.map { x =>
        val userIdDir = tool.getUserIdDir(userId)
        Utils.deleteDirectory(userIdDir)
        Ok("success!")
      }
    } else {
      Future.successful(Forbidden("Forbidden!"))
    }
  }

  def toHome = Action { implicit request =>
    val domain = tool.getRequestDomain
    Redirect(s"http://${domain}/project/platformHome")
  }

  def logout = Action { implicit request =>
    val domain = tool.getRequestDomain
    Redirect(s"http://${domain}/").flashing("info" -> "退出登录成功!").withNewSession
  }


}
